package main

import (
	"fmt"
)

func main() {
	/*
		1.接口：interface
			在 Go 中，接口是一组方法签名
			接口是Go语言类型系统的灵魂，是Go语言多态和反射的基础

			当某个类型为这个接口中的所有方法提供了方法的实现，它就被称为实现接口

			Go语言中，接口和类型的实现关系，是非侵入式
			//其他语言中，要显示的定义
				eg: class Mouse interface USB{}

			1.当需要接口类型的对象时，可以使用任意实现类对象代替
			2.接口对象不能访问实现类中的属性


		2.多态：一个事物的多种形态
			go语言通过接口模拟多态

			就一个接口的实现来说：
				1.看成实现本身的类型，能够访问实现类中的属性和方法
				2.看成是对应的接口类型，那就只能够访问接口中的方法

		3.接口的用法：
			1.一个函数如果接受接口类型作为参数，那么实际上可以传入该接口的任意实现类型对象作为参数
			2.定义一个类型为接口类型，实际上可以赋值为任意实现类的对象

		鸭子类型：是对于动态语言来说的，它更关注的是对象如何被使用，而不是对象本身
				即只关心事物的外部行为而非内部结构

		4.接口的优点：
		（1）解耦：Go 的非侵入式的接口，使层与层之间的代码更加干净，具体类型和实现的接口之间不需要显式地声明，增加了接口使用的自由度
		（2）实现泛型：Go 目前不支持泛型，使用空接口作为函数或方法的参数能够用在需要泛型的场景中

		5.接口的使用：
		（1）作为结构内嵌字段
		（2）作为函数或方法的形参
		（3）作为函数或方法的返回值
		（4）作为其他接口定义的嵌入字段

	*/
	//1.创建 Mouse 类型
	m1 := Mouse{"Jerry"}
	fmt.Println(m1.name)
	//2.创建 FlashDisk 类型
	f1 := FlashDisk{"360"}
	fmt.Println(f1.name)

	testInterface(m1)
	testInterface(f1)

	var usb USB
	usb = m1
	usb.start()
	usb.end()
	//fmt.Println(usb.name)

	var arr [3]USB
	arr[0] = m1
	arr[1] = f1
	fmt.Println(arr) //[{Jerry} {360} <nil>]
}

// 1.定义接口
type USB interface {
	start() //USB设备开始工作
	end()   //USB设备结束工作
}

// 2.实现类
type Mouse struct {
	name string
}

type FlashDisk struct {
	name string
}

func (m Mouse) start() {
	fmt.Println(m.name, "鼠标，准备就绪，可以开始工作，点点点。。。")
}

func (m Mouse) end() {
	fmt.Println(m.name, "结束工作，可以安全退出。。。")
}

func (f FlashDisk) start() {
	fmt.Println(f.name, "准备开始工作，可以进行数据存储。。。")
}

func (f FlashDisk) end() {
	fmt.Println(f.name, "可以弹出。。。")
}

// 3.测试方法
func testInterface(usb USB) { //usb = m1, usb = f1
	usb.start()
	usb.end()
}
